package zserver

import (
	"errors"
	"fmt"
	"io"
	"net"
	"zinx/zinterface"
)

type ZConnector struct {
	ConnId   uint32             // 1. id
	Conn     *net.TCPConn       // 2. socket套接字
	isClosed bool               // 3. 当前的状态

	// Router   zinterface.IRouter // 路由
	// 0.6版本修改为使用MsgHandler管理路由
	MsgHandler zinterface.IMsgHandler

	ExitChan chan bool          // 5. 等待连接推出的channel

}

func NewConnector(conn *net.TCPConn, id uint32, msgHandler zinterface.IMsgHandler) *ZConnector {
	zc := &ZConnector{
		ConnId:   id,
		Conn:     conn,
		isClosed: false,
		ExitChan: make(chan bool, 1),
		MsgHandler: msgHandler,
	}

	return zc
}

/*
	实现iconnector接口
*/

func (zc *ZConnector) StartReader() {
	fmt.Println("Reader goroutine is running...")
	defer fmt.Println("Connection: ", zc.ConnId, " is STOPPING, RemoteAddr is: ", zc.Conn.RemoteAddr().String())
	defer zc.Stop()

	for {
		// 读取客户端发送的字节
		// buf := make([]byte, utils.GlobalObject.MaxPackageSize)
		// _, err := zc.Conn.Read(buf)
		// if err != nil {
		// 	fmt.Println("!!!ERROR When Reading From Client: ", err)
		// 	zc.ExitChan <- true
		// 	continue
		// }
		// 由新的datapack实例来读取

		zdp := NewDataPack()

		// 先读取8个字节的消息头
		headBuf := make([]byte, zdp.GetHeadLength())
		if _, err := io.ReadFull(zc.GetTCPConnection(), headBuf); err != nil {
			fmt.Println("!!!ERROR When Reading Head From Client: ", err)
			zc.ExitChan <- true
			break
		}

		// 对消息头进行解包
		msg, err := zdp.UnPack(headBuf)
		if err != nil {
			fmt.Println("!!!ERROR When UnPack Head: ", err)
			zc.ExitChan <- true
			break
		}

		// 读取消息体，放在msg.Data中
		var bodyBuf []byte
		if msg.GetMsgLength() > 0 {
			bodyBuf = make([]byte, msg.GetMsgLength())
			if _, err := io.ReadFull(zc.GetTCPConnection(), bodyBuf); err != nil {
				fmt.Println("!!!ERROR When Read MsgBody: ", err)
				zc.ExitChan <- true
				break
			}

			msg.SetMsgData(bodyBuf)
		}


		req := &ZRequest{
			conn: zc,
			msg: msg,
		}

		//调用router中的处理方法
		// go func(request	zinterface.IRequest) {
		// 	zc.Router.PreHandle(request)
		// 	zc.Router.Handle(request)
		// 	zc.Router.PostHandle(request)
		// }(req)
		// 0.6版本修改为使用MsgHandler
		go zc.MsgHandler.DoRouter(req)

	}

}

func (zc *ZConnector) Start() {
	fmt.Println("START CONNECTION: ", zc.ConnId)

	// 启动读goroutine
	go zc.StartReader()

	// TODO: 启动写goroutine

}

func (zc *ZConnector) Stop() {
	fmt.Println("Start STOP CONNECTION: ", zc.ConnId)

	if zc.isClosed {
		fmt.Println("CONNECTION ", zc.ConnId, " has already closed!")
		return
	}

	// 关闭连接，释放资源
	zc.isClosed = true

	zc.Conn.Close()

	close(zc.ExitChan)
}

func (zc *ZConnector) GetTCPConnection() *net.TCPConn {
	return zc.Conn
}

func (zc *ZConnector) GetRemoteAddr() net.Addr {
	return zc.Conn.RemoteAddr()
}

func (zc *ZConnector) GetId() uint32 {
	return zc.ConnId
}

func (zc *ZConnector) IsClosed() bool {
	return zc.isClosed
}

// 发送Message到客户端
func (zc *ZConnector) SendMsg(msgId uint32, msgData []byte) error {
	// 判断连接是否已经关闭
	if zc.isClosed {
		return errors.New("SendMsg Error: clinet is closed")
	}

	// 对消息进行pack
	zdp := NewDataPack()
	binaryMsg, err := zdp.Pack(NewMessage(msgId, msgData))
	if err != nil {
		fmt.Println("error when pack messageid: ", msgId, " ", err)
		return err
	}

	// 发送消息
	if _, err := zc.GetTCPConnection().Write(binaryMsg); err != nil {
		fmt.Println("error when send messageid: ", msgId, " ", err)
		return err
	}

	return nil
}
